#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# blipoc - Blip On Console
#
# author: Cezary Statkiewicz (cezio [at] thelirium.net), Patryk Zawadzki <patrys@pld-linux.org>
# website: http://code.google.com/p/blipoc/
#


import os, sys, atexit, curses, time, datetime
from pprint import pprint
import thread, threading
import blipy

blipy.core.USER_AGENT = "blipoc"

def get_status(cli_options, config):
    username, password = config.get('user', 'username'), config.get('user', 'password')
    status_id = cli_options.get_status
    a = blipy.Account()
    a.set_credentials(username, password)
    status = blipy.Status.get(a, status_id)
    _s = 'od: %s data: %s (transport: %s): http://blip.pl/s/%s \n\t%s\n'%( status.user.login, status.created_at, status.transport.name, status.id, status.body)
    try:
        print _s.encode(config.get('settings', 'encoding'))
    except UnicodeEncodeError, e:
        print _s.encode('utf-8')


def set_status(cli_options, config):
    username, password = config.get('user', 'username'), config.get('user', 'password')
    status = cli_options.set_status.decode(config.get('settings', 'encoding')).encode('utf-8')
    a = blipy.Account()
    a.set_credentials(username, password)
    picture = getattr(cli_options, 'picture', None)
    picture_struct = None
    if picture:
        try:
            f = open(picture, 'r')
            picture_content = f.read()
            picture_struct = [os.path.basename(picture), picture_content]
        finally:
            f.close()
    data = blipy.Update.create(a, status, picture_struct)
    pprint(data)

def friends(cli_options, config):
    username, password = config.get('user', 'username'), config.get('user', 'password')
    a = blipy.Account()
    a.set_credentials(username, password)
    data = blipy.User.friends(a)
    _s = u'Przyjaciele użytkownika %s' % username
    print _s.encode(config.get('settings', 'encoding'))
    for f in data:
        _s = '\t%s [%s] @ %s: \n\t\t%s'%(f.login, f.id, getattr(f.current_status, 'created_at', ''), getattr(f.current_status, 'body', ''))
        try:
            print _s.encode(config.get('settings', 'encoding'))
        except UnicodeEncodeError, e:
            print _s.encode('utf-8')

def subscriptions(cli_options, config):
    username, password = config.get('user', 'username'), config.get('user', 'password')
    if cli_options.subscriptions is not True:
        sub_username = cli_options.subscriptions
    else:
        sub_username = username
    a = blipy.Account()
    a.set_credentials(username, password)
    _s = u'Kontakty użytkownika %s' % sub_username

    def _get_subscriptions(user, direction, attribute):
        """
        gets subscriptions for user for directions (FROM, TO)
        gets 
        """
        data = blipy.Subscription.get( a, user, direction)
        subscriptions = {}
        for f in data:
            try:
                subscriptions[getattr(f, attribute)].append(f.transport)
            except KeyError:
                subscriptions[getattr(f, attribute)] =  [f.transport]
        keys = subscriptions.keys()
        keys.sort()
        out = []
        for k in keys:
            out.append( [blipy.user_from_path(a, k),  subscriptions[k]])

        return user, out


    _user, subscribers = _get_subscriptions(sub_username, blipy.SUB_FROM, 'tracked_user_path')

    _s = u' użytkownik %s obserwuje: \n%s'%( _user, 
            '\n'.join( ' %s przez %s'%(k.login,  ','.join([ v.name for v in t] )) 
                                            for k, t in subscribers ) )
    print _s.encode(config.get('settings', 'encoding'))


    _user, subscribers = _get_subscriptions(sub_username, blipy.SUB_TO, 'tracking_user_path')
    print ''
    _s = u' użytkownik %s jest obserwowany przez: \n%s'%( _user, 
            '\n'.join( ' %s przez %s'%(k.login,  ','.join([ v.name for v in t] )) 
                                            for k, t in subscribers ) )
    print _s.encode(config.get('settings', 'encoding'))


def bliposphere(cli_options, config):
    username, password = config.get('user', 'username'), config.get('user', 'password')
    a = blipy.Account()
    a.set_credentials(username, password)
    data = blipy.Bliposphere.list(a)
    _s = u'Bliposfera'
    print _s.encode(config.get('settings', 'encoding'))
    data.reverse()
    for d in data:
        _s = 'od: %s data: %s (transport: %s): http://blip.pl/s/%s \n\t%s\n'%( d.user.login, d.created_at, d.transport.name, d.id, d.body)
        try:
            print _s.encode(config.get('settings', 'encoding'))
        except UnicodeEncodeError, e:
            print _s.encode('utf-8')

def tag(cli_options, config):
    username, password = config.get('user', 'username'), config.get('user', 'password')
    tag = cli_options.tag
    a = blipy.Account()
    a.set_credentials(username, password)
    data = blipy.Status.tags(a, tag)
    _s = u'Tag %s'%tag
    print _s.encode(config.get('settings', 'encoding'))
    data.reverse()
    for d in data:
        _s = 'od: %s data: %s (transport: %s): http://blip.pl/s/%s \n\t%s\n'%( d.user.login, d.created_at, d.transport.name, d.id, d.body)
        try:
            print _s.encode(config.get('settings', 'encoding'))
        except UnicodeEncodeError, e:
            print _s.encode('utf-8')


def dashboard(cli_options, config):
    username, password = config.get('user', 'username'), config.get('user', 'password')
    if cli_options:
        dashboard = cli_options.dashboard
    else:
        dashboard = None
    a = blipy.Account()
    a.set_credentials(username, password)
    data = blipy.Update.dashboard(a, dashboard)
    _s = u'Kokpit użytkownika %s' % username
    print _s.encode(config.get('settings', 'encoding'))
    #pprint(data)
    data.reverse()
    
    for d in data:
        if isinstance(d, blipy.Notice):
            _s = u'powiadomienie: %s (data: %s)\n'%(d.body, d.created_at)
            
        elif isinstance(d, blipy.DirectedMessage):
            _s = u'wiadomość od %s dla %s data: %s (transport: %s) http://blip.pl/dm/%s \n\t%s\n'%(d.user.login, 
                                                                                                   d.recipient.login, 
                                                                                                   d.created_at,
                                                                                                   d.transport.name,
                                                                                                   d.id,
                                                                                                   d.body, )
        elif isinstance(d, blipy.PrivateMessage):
            _s = u'prywatna wiadomość od %s dla %s data: %s (transport: %s) http://blip.pl/dm/%s \n\t%s\n'%(d.user.login, 
                                                                                                   d.recipient.login, 
                                                                                                   d.created_at,
                                                                                                   d.transport.name,
                                                                                                   d.id,
                                                                                                   d.body, )

        elif isinstance(d, blipy.Update):
            _s = u'od: %s data: %s (transport: %s) http://blip.pl/s/%s \n\t%s\n'%( d.user.login, 
                                d.created_at, 
                                d.transport.name, 
                                d.id,
                                d.body)
        else:
            print 'Nieznany typ komunikatu: %s: %s'%(d.__class__, d)
        try:
            print _s.encode(config.get('settings', 'encoding'))
        except UnicodeEncodeError, e:
            print _s.encode('utf-8')

def user(cli_options, config):
    username, password = config.get('user', 'username'), config.get('user', 'password')
    user_id  = None
    if cli_options and cli_options.user:
        user_id = cli_options.user
    a = blipy.Account()
    a.set_credentials(username, password)
    data = blipy.User.get(a, user_id)
    if not data:
        _s = u'Nie znaleziono użytkownika o id %s'%user_id
        print _s.encode(config.get('settings', 'encoding'))
        return
    if getattr(data.current_status, 'body', ''):
        _s = u'Informacja o użytkowniku %s [%s] \n\t%s [%s]:\n\t %s'%(data.login,
                                                    data.id,
                                                    getattr(data.current_status, 'created_at', ''),
                                                    getattr(data.current_status, 'id',''),
                                                    getattr(data.current_status, 'body', ''))
        print _s.encode(config.get('settings', 'encoding'))
    else:
        _s = u'Informacja o użytkowniku %s [%s] \n\t(nie ma ustawionego statusu)'%(data.login,
                                                    data.id)
        print _s.encode(config.get('settings', 'encoding'))
    print data.current_status.recording
    print data.avatar
    print data.background

class CommandQueue(threading.Thread):
    def __init__(self, after_callback = None, max_commands = 5, *args, **kwargs):
        threading.Thread.__init__(self, *args, **kwargs)
        self._commands = []
        self.lock = threading.Lock()
        self._close = False
        self.after_callback = after_callback
        self.max_commands = max_commands
    
    def add_command(self, cmd, *args, **kwargs):
        self.lock.acquire()
        self._commands.append((cmd, args, kwargs,))
        self.lock.release()
        
    def close(self):
        print 'closing...'
        self._close = True
        
    def run(self):
        while not self._close:
            time.sleep(0.5)
            print 'tasks..', len(self._commands)
            while len(self._commands):
                self.lock.aquire()
                counter = 0
                while len(self._commands):
                    if counter> self.max_commands:
                        break
                    cmd = self._commands.pop()
                    cmd[0](*cmd[1], **cmd[2])
                    counter += 1
                self.lock.release()
        if self.after_callback:
            self.after_callback()

class CommandDispatcher(object):
    commands = []
    def __init__(self):
        pass
    
    def install_command(self, cmd_func, *args, **kwargs):
        """
        """
        CommandDispatcher.commands.append(( cmd_func, args, kwargs,))

    def run(self):
        """
        """
        while len(CommandDispatcher.commands):
            cmd = CommandDispatcher.commands.pop(0)
            cmd[0]( *cmd[1], **cmd[2])

    def parse_commands(self, cli_options, config):
        """
        parsuje polecenia z cli
         - ustawienie statusu,
         - pobranie dashboarda
         - pobranie listy przyjaciol
         
         
        instaluje polecenia
        """
        if getattr(cli_options, 'bliposphere', None):
            self.install_command(bliposphere, cli_options, config)
        if getattr(cli_options, 'dashboard', None):
            self.install_command(dashboard, cli_options, config)
        if getattr(cli_options, 'set_status', None):
            self.install_command(set_status, cli_options, config)
        if getattr(cli_options, 'friends', None):
            self.install_command(friends, cli_options, config)
        if getattr(cli_options, 'user', None):
            self.install_command(user, cli_options, config)
        if getattr(cli_options, 'tag', None):
            self.install_command(tag, cli_options, config)
        if getattr(cli_options, 'subscriptions', None):
            self.install_command(subscriptions, cli_options, config)
        if getattr(cli_options, 'get_status', None):
            self.install_command(get_status, cli_options, config)



class BlipocApp(object):
    """
    interaktywna część
    """
    def __init__(self, commands):
        self.commands = commands
        self._screen_cmds = []
        atexit.register(self.__del__)
        self.queue = CommandQueue()
        
    def run(self):
        """
        """
        print 'run..'
        # curses init
        #self.stdscr = curses.initscr()
        #curses.noecho()
        #curses.cbreak()
        #self.stdscr.keypad(1)
        self.queue.start()
        
        time.sleep(1)
        
    def __del__(self):
        self.queue.close()
        if self.queue.isAlive():
            self.queue.join(0.1)
        #curses.endwin()
        
        
# version: $Id: app.py 50 2009-07-12 15:30:53Z c.statkiewicz $
